package com.wg.net.peer;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wg.core.thread.fiber.IFiber;
import com.wg.core.thread.fiber.PoolFiber;
import com.wg.core.utils.ThreadUtils;
import com.wg.game.app.BaseApplication;
import com.wg.net.DisconnectReason;
import com.wg.net.operations.InitRequest;

import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 托管对端实现类（协调网络层与应用层的交互）
 * <p>
 * 职责：
 * - 封装纤维（Fiber）的异步任务调度
 * - 管理对端连接的创建与销毁生命周期
 * - 处理应用层与网络层的事件传递
 *
 * @author 少爷123
 */
public class ManagedPeer implements IManagedPeer {
    private static final Log log = LogFactory.get();

    /**
     * 纤维调度器（用于异步执行任务）
     */
    private final IFiber fiber;

    /**
     * 应用层核心对象（业务逻辑载体）
     */
    private final BaseApplication application;

    /**
     * 断开状态标记（原子操作保证线程安全）
     */
    private final AtomicBoolean disconnected = new AtomicBoolean(false);

    /**
     * 网络层对端对象（由应用层创建）
     */
    private BasePeer peer;

    /**
     * 对端创建状态（避免重复创建）
     */
    private PeerCreationState peerCreationState;

    /**
     * 构造托管对端（初始化纤维与状态）
     *
     * @param request     初始化请求（包含连接参数）
     * @param application 应用层核心对象
     */
    public ManagedPeer(InitRequest request, BaseApplication application) {
        this.application = application;
        this.fiber = new PoolFiber();
        this.peerCreationState = PeerCreationState.Started;
        request.setRequestFiber(this.fiber);
        this.fiber.enqueue(() -> createPeerBase(request));
    }

    /**
     * 静态工厂方法（创建并启动托管对端）
     *
     * @param initRequest 初始化请求
     * @param application 应用层核心对象
     */
    public static void create(InitRequest initRequest, BaseApplication application) {
        ManagedPeer managedPeer = new ManagedPeer(initRequest, application);
        initRequest.getPeer().setUserData(managedPeer);
        managedPeer.fiber.start();
    }

    @Override
    public boolean applicationOnDisconnect(DisconnectReason reasonCode, String reasonDetail) {
        // 防止重复调用（原子操作保证线程安全）
        if (!disconnected.compareAndSet(false, true)) {
            log.warn("重复触发断开回调 | 线程栈: {}", ThreadUtils.printStackTrace());
            return false;
        }

        // 异步执行断开逻辑（避免阻塞当前线程）
        this.fiber.enqueue(() -> handleDisconnect(reasonCode, reasonDetail));
        return true;
    }

    @Override
    public void applicationOnReceive(byte[] data) {
        // 异步执行消息处理（避免阻塞网络线程）
        this.fiber.enqueue(() -> handleReceive(data));
    }

    /**
     * 实际处理断开逻辑（异步）
     *
     * @param reasonCode   断开原因代码
     * @param reasonDetail 断开详细说明
     */
    private void handleDisconnect(DisconnectReason reasonCode, String reasonDetail) {
        BasePeer peer = this.peer;
        if (peer != null) {
            peer.onApplicationDisconnect(reasonCode, reasonDetail);
        } else if (peerCreationState != PeerCreationState.Failed && log.isErrorEnabled()) {
            log.error("对端断开时应用层对象未创建 | 断开原因: {}, 详细信息: {}", reasonCode, reasonDetail);
        }
    }

    /**
     * 实际处理消息接收逻辑（异步）
     *
     * @param data 接收到的字节数据
     */
    private void handleReceive(byte[] data) {
        BasePeer peer = this.peer;
        if (peer != null) {
            peer.onReceiveInternal(data);
        } else if (peerCreationState != PeerCreationState.Failed && log.isErrorEnabled()) {
            log.error("对端接收消息时应用层对象未创建 | 数据长度: {}", data.length);
        }
    }

    /**
     * 创建网络层对端对象（异步）
     *
     * @param request 初始化请求
     */
    private void createPeerBase(InitRequest request) {
        try {
            this.peer = application.createPeerInternal(request);
            if (peer == null) {
                peerCreationState = PeerCreationState.Failed;
                request.getPeer().close(); // 创建失败时关闭底层连接
            } else {
                peerCreationState = PeerCreationState.Succeeded;
                peer.initialize(request); // 初始化网络层对端
                application.incrementPeerCounter(); // 统计对端数量
            }
        } catch (Exception e) {
            log.error("对端创建失败 | 初始化请求: {}", request, e);
            peerCreationState = PeerCreationState.Failed;
            request.getPeer().close();
        }
    }

    /**
     * 对端创建状态枚举
     */
    private enum PeerCreationState {
        /**
         * 创建已启动
         */
        Started,    
        /**
         * 创建成功
         */
        Succeeded,
        /**
         * 创建失败
         */
        Failed
    }
}